package com.csyf.manager.controller.api;

import com.alibaba.fastjson.JSONObject;
import com.csyf.manager.entity.SysAliAccount;
import com.csyf.manager.entity.SysTrade;
import com.csyf.manager.service.OrderBiz;
import com.csyf.manager.service.OrderService;
import com.csyf.manager.service.SysAliAccountBiz;
import com.csyf.manager.service.impl.RedisService;
import com.csyf.manager.utils.HttpHelper;
import com.csyf.manager.utils.NumberHelpler;
import com.csyf.manager.utils.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Enzo
 * @Date: 2018/3/29 14:16
 */
@Slf4j
@Controller
@RequestMapping(value = "notify")
public class NotifyController {

    private static final String SUCCESS = "SUCCESS";

    @Autowired
    private OrderBiz orderBiz;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SysAliAccountBiz sysAliAccountBiz;

    @ResponseBody
    @RequestMapping(value = "testnotify")
    public String testnotify(HttpServletRequest request) {

        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();

        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String name = (String) parameterNames.nextElement();
            String value = request.getParameter(name);
            log.info("接受参数:{}={}", name, value);

        }
        return "success";
    }

    @ResponseBody
    @RequestMapping(value = "cspayNotify")
    public String cspayNotify(HttpServletRequest request) {
        TreeMap<String, String> params = getParams(request);

        String mch_id = request.getParameter("mch_id");
        String out_trade_no = request.getParameter("out_trade_no");
        String service = request.getParameter("service");
        //TRADE_SUCCESS：交易成功  TRADE_FAILE：交易失败   WAIT_BUYER_PAY：交易处理中
        String tradeStatus = request.getParameter("tradeStatus");
        String total_fee = request.getParameter("total_fee");
        log.info("[{}]接受到上游回调参数：{}", out_trade_no, params);
        if ("TRADE_SUCCESS".equals(tradeStatus)) {
            orderBiz.orderSuccess(out_trade_no, "00", "支付成功");
            String downnotify = downnotify(out_trade_no);
            if (SUCCESS.equalsIgnoreCase(downnotify)) {
                return "SUCCESS";
            } else {
                return downnotify;
            }
        }
        return "FAILE";
    }

    /**
     * 糯米支付 回调
     *
     * @param request
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "nmpaynotify")
    public String nmpaynotify(HttpServletRequest request, @RequestBody String rspParam) throws IOException {
        getParams(request);
        log.info("糯米支付 回调开始....");

        if ("=".equals(rspParam.substring(rspParam.length() - 1))) {
            rspParam = rspParam.substring(0, rspParam.length() - 1);
        }

        String decode = URLDecoder.decode(rspParam, "UTF-8");
        log.info("糯米支付 回调接受参数：{}", decode);

        JSONObject jsonObject = JSONObject.parseObject(decode);
        JSONObject notify_msg = jsonObject.getJSONObject("notify_msg");
        String order_no = notify_msg.getString("order_no");
        String trade_status = notify_msg.getString("trade_status");
        String trade_no = notify_msg.getString("trade_no");

        if ("SUCCESS".equals(trade_status)) {
            orderBiz.orderSuccess(order_no, "0000", "交易成功", trade_no);
            String downnotify = downnotify(order_no);
            if (SUCCESS.equalsIgnoreCase(downnotify)) {
                return SUCCESS.toLowerCase();
            } else {
                return downnotify;
            }
        } else {
            return "false";
        }
    }

    /**
     * 拼多多 回调
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "pddNotify")
    public String pddNotify(HttpServletRequest request) {
        getParams(request);
        log.info("拼多多 回调开始....");

        String callbacks = request.getParameter("callbacks");
        String api_order_sn = request.getParameter("api_order_sn");
        String order_sn = request.getParameter("order_sn");

        if ("CODE_SUCCESS".equals(callbacks)) {
            orderBiz.orderSuccess(api_order_sn, "0000", "支付成功", order_sn);
            String downnotify = downnotify(api_order_sn);
            if (SUCCESS.equalsIgnoreCase(downnotify)) {
                return "OK";
            } else {
                return downnotify;
            }
        }
        return "fail";
    }


    /**
     * 给下游发送消息
     *
     * @param orderNo
     * @return
     */
    private String downnotify(String orderNo) {
        SysTrade sysTrade = orderService.queryOrderByOrderNo(orderNo);


        //存储当日的交易总额
        String key = "trade:order:" + sysTrade.getOutTradeNo();

        String key1 = redisService.get(key);
        if (null == key1) {
            String yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(sysTrade.getCreateTime());

            //BEGIN 存储上游商户 交易 金额
            String srcmchkey = "trade:srcmch:" + yyyyMMdd + ":" + sysTrade.getSrcMchId();
            BigDecimal totalmoney = redisAdd(srcmchkey, sysTrade.getTotalFee(), 48 * 60 * 60);

            SysAliAccount byAppid = sysAliAccountBiz.findByAppid(sysTrade.getSrcMchId());
            //账号表中有，并且交易金额超出通道的交易上限，将通道关停
            if (null != byAppid && totalmoney.compareTo(byAppid.getDailyLimit()) > 0) {
                sysAliAccountBiz.quotaAll(byAppid.getAppid());
            }
            //END 存储上游商户 交易 金额

            //BEGIN 存储上游商户 收益 金额
            String srcmchkey_profit = "trade:srcmch_profit:" + yyyyMMdd + ":" + sysTrade.getSrcMchId();
            redisAdd(srcmchkey_profit, sysTrade.getProfit().add(sysTrade.getCostprofit()), 48 * 60 * 60);
            //BEGIN 存储上游商户 收益 金额

            //BEGIN 存储上游商户 交易笔数
            String srcmchkey_count = "trade:srcmch_count:" + yyyyMMdd + ":" + sysTrade.getSrcMchId();
            redisAdd(srcmchkey_count, BigDecimal.ONE, 48 * 60 * 60);
            //BEGIN 存储上游商户交易笔数


            //BEGIN 存储商户 交易金额
            String mch_key = "trade:mch:" + yyyyMMdd + ":" + sysTrade.getMchId();
            redisAdd(mch_key, sysTrade.getTotalFee(), 48 * 60 * 60);
            //END 存储商户交易交易金额


            //BEGIN 存储商户 交易金额
            String mch_key_count = "trade:mch_count:" + yyyyMMdd + ":" + sysTrade.getMchId();
            redisAdd(mch_key_count, BigDecimal.ONE, 48 * 60 * 60);
            //END 存储商户交易交易金额

            //BEGIN 存储商户 收益 金额
            String mch_profit_key = "trade:mch_profit:" + yyyyMMdd + ":" + sysTrade.getMchId();
            redisAdd(mch_profit_key, sysTrade.getProfit(), 48 * 60 * 60);
            //END 存储商户交易 收益 金额

            redisService.set(key, new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()), 24 * 60 * 60);
        }


        if (null != sysTrade) {
            Map<String, String> hashMap = new TreeMap();
            hashMap.put("out_trade_no", sysTrade.getOutTradeNo());
            hashMap.put("mch_id", sysTrade.getMchId());
            hashMap.put("service", sysTrade.getServiceType());
            hashMap.put("tradeStatus", sysTrade.getTradeStatus());
            hashMap.put("total_fee", NumberHelpler.money2cent(sysTrade.getTotalFee()).toString());
            String agentSignKey = getAgentSignKey(sysTrade.getMchId());
            String sign = SignUtils.map2signkey(hashMap, agentSignKey);
            hashMap.put("sign", sign);
            log.info("[{}] [{}] ,请求参数:{}", orderNo, sysTrade.getNotifyUrl(), hashMap);
            String s = HttpHelper.doPostForm(sysTrade.getNotifyUrl(), hashMap);
            log.info("[{}] [{}] ,接受参数:{}", orderNo, sysTrade.getNotifyUrl(), s);
            return s;
        }
        return null;


//        SysTrade sysTrade = orderService.queryOrderByOrderNo(orderNo);
//        if (null != sysTrade) {
//            if (StringUtils.isNotBlank(sysTrade.getNotifyStatus()) && "0-0".equals(sysTrade.getNotifyStatus())) {
//                Map<String, String> hashMap = new TreeMap();
//                hashMap.put("out_trade_no", sysTrade.getOutTradeNo());
//                hashMap.put("mch_id", sysTrade.getMchId());
//                hashMap.put("service", sysTrade.getServiceType());
//                hashMap.put("tradeStatus", sysTrade.getTradeStatus());
//                hashMap.put("total_fee", NumberHelpler.money2cent(sysTrade.getTotalFee()).toString());
//                String agentSignKey = getAgentSignKey(sysTrade.getMchId());
//                String sign = SignUtils.map2signkey(hashMap, agentSignKey);
//                hashMap.put("sign", sign);
//                log.info("[{}] [{}] ,请求参数:{}", orderNo, sysTrade.getNotifyUrl(), hashMap);
//                String s = HttpHelper.doPostForm(sysTrade.getNotifyUrl(), hashMap);
//                log.info("[{}] [{}] ,接受参数:{}", orderNo, sysTrade.getNotifyUrl(), s);
//
//                String notify = orderBiz.updateNotifyStatus(sysTrade, s);
//                log.info("[{}] 回调成功，修改回调状态={}", orderNo, notify);
//                return s;
//            }
//        }
//        return null;
    }


    /**
     * reids 中的值进行累加
     *
     * @param key   key
     * @param value 累加的值
     * @param time  累加的保存的时效性
     * @return
     */
    private BigDecimal redisAdd(String key, BigDecimal value, long time) {
        BigDecimal totalmoney = BigDecimal.ZERO;
        String money = redisService.get(key);

        totalmoney = null == money ? value : NumberHelpler.add(money, value);
        redisService.set(key, totalmoney.toString(), time);

        return totalmoney;
    }

    /**
     * 动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容由于收银宝加字段而引起的签名异常
     *
     * @param request
     * @return
     */
    private TreeMap<String, String> getParams(HttpServletRequest request) {
        TreeMap<String, String> map = new TreeMap<String, String>();


        Map reqMap = request.getParameterMap();
        for (Object key : reqMap.keySet()) {
            String value = ((String[]) reqMap.get(key))[0];
            log.info("接受参数:{}={}", key, value);
            map.put(key.toString(), value);
        }
        return map;
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public String getAgentSignKey(String mch_id) {

        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String s = stringStringValueOperations.get("signkey:" + mch_id);
        return s;
    }


    public String getPayAbbr(String payAbbr, String key) {
        String returnVal = "";
        Map<String, String> payMap = new HashMap<>();

        String[] payArr = payAbbr.split("\\|");
        for (String s : payArr) {
            String[] ms = s.split("=");
            payMap.put(ms[0], ms[1]);
        }

        if (null != payMap) {
            returnVal = payMap.get(key);
        }
        return returnVal;
    }

}
